from abc import ABC, abstractmethod
from fly import *
from quack import *


class Duck(ABC):
    def __init__(self, fb: FlyBehavior = None, qb: QuackBehavior = None):
        self._fly_behavior = fb
        self._quack_behavior = qb

    @property
    def fly_behavior(self) -> FlyBehavior:
        return self._fly_behavior

    @fly_behavior.setter
    def fly_behavior(self, value: FlyBehavior):
        self._fly_behavior = value

    @abstractmethod
    def display(self):
        ...

    def perform_fly(self):
        self._fly_behavior.fly()

    def perform_quack(self):
        self._quack_behavior.quack()

    @staticmethod
    def swim():
        print("All ducks float, even decoys")


class DecoyDuck(Duck):
    def display(self):
        print("I'm a duck Decoy")

    def __init__(self):
        super().__init__(FlyNoWay(), MuteQuack())


class MallardDuck(Duck):
    def display(self):
        print("I'm a real Mallard duck")

    def __init__(self):
        super().__init__(FlyWithWings(), Quack())


class ModelDuck(Duck):
    def display(self):
        print("I'm a model duck")

    def __init__(self):
        super().__init__(FlyNoWay(), Quack())


class RedHeadDuck(Duck):
    def display(self):
        print("I'm a real Red Headed duck")

    def __init__(self):
        super().__init__(FlyWithWings(), Quack())


class RubberDuck(Duck):
    def display(self):
        print("I'm a rubber duckie")

    def __init__(self):
        super().__init__(FlyNoWay(), Squeak())
